package com.ficus.road.maintain.util;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import com.ficus.road.maintain.config.AliyunOssConfig;
import com.ficus.road.maintain.core.model.oss.AliyunOssResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;


/**
 * 阿里云oss工具类
 *
 * @author shiye
 * @create 2020-06-10 14:09
 */
@Component
@Slf4j
public class AliyunOSSUtil {
    @Autowired
    private OSSClient ossClient;
    @Autowired
    private AliyunOssConfig aliyunOssConfig;

    /**
     * int to byte[]
     *
     * @param a
     * @return
     */
    public static byte[] intToByteArray(int a) {
        return new byte[]{
                (byte) ((a >> 24) & 0xFF),
                (byte) ((a >> 16) & 0xFF),
                (byte) ((a >> 8) & 0xFF),
                (byte) (a & 0xFF)
        };
    }

    public static int byteArrayToInt(byte[] bytes) {
        return ((bytes[0] & 0xFF) << 24) |
                ((bytes[1] & 0xFF) << 16) |
                ((bytes[2] & 0xFF) << 8) |
                ((bytes[3] & 0xFF) << 0);
    }

    /**
     * @param fileUrl 文件url
     * @return String fileName
     * @MethodName: getFileName
     * @Description: 根据url获取fileName
     */
    public static String getFileName(String fileUrl) {
        String str = "aliyuncs.com/";
        int beginIndex = fileUrl.indexOf(str);
        if (beginIndex == -1)
            return null;
        return fileUrl.substring(beginIndex + str.length());
    }

    /**
     * 根据url获取文件的
     *
     * @param url
     * @return
     * @throws IOException
     */
    public OSSObject getFileByUrl(String url) throws IOException {
        String fileName = getFileName(url);
        return ossClient.getObject(aliyunOssConfig.getBucketName(), fileName);
    }

    /**
     * 指定文件名上传文件
     *
     * @param fileName 文件名
     * @param bytes
     * @return
     */
    public Long uploadData(String fileName, byte[] bytes) {
        try {
            PutObjectRequest putObjectRequest = new PutObjectRequest(aliyunOssConfig.getBucketName(), fileName, new ByteArrayInputStream(bytes));
            PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
            return putObjectResult.getServerCRC();
        } catch (OSSException | ClientException e) {
            log.error("oss upload file met exception:", e);
            return null;
        }
    }

    public OSSObject getFile(String fileName) {
        return ossClient.getObject(aliyunOssConfig.getBucketName(), fileName);
    }


    /**
     * 上传文件
     *
     * @param input
     * @param fileType
     * @param fileName
     * @return
     */
    public AliyunOssResult putFile(InputStream input, String fileType, String fileName) {
        AliyunOssResult resoult = null;

        //初始化客户端
        try {
            // 创建上传Object的Metadata
            ObjectMetadata meta = new ObjectMetadata();
            // 设置上传内容类型
            meta.setContentType(fileType);
            //被下载时网页的缓存行为
            meta.setCacheControl("no-cache");
            //创建上传请求
            PutObjectRequest request = new PutObjectRequest(aliyunOssConfig.getBucketName(), fileName, input, meta);
            //上传文件
            ossClient.putObject(request);

            //获取上传成功的文件地址
            resoult = new AliyunOssResult(200, getOssUrl(fileName), fileName, null);
        } catch (OSSException | ClientException e) {
            log.error("oss upload file met exception:", e);
            resoult = new AliyunOssResult(400, null, null, e.getMessage());
            return resoult;
        }
        return resoult;
    }

    /**
     * 根据文件名生成文件的访问地址
     *
     * @param key
     * @return
     */
    public String getOssUrl(String key) {
        Date expiration = new Date(new Date().getTime() + AliyunOssConfig.FILE_EXPIRATION_TIME);// 生成URL
        GeneratePresignedUrlRequest generatePresignedUrlRequest;
        generatePresignedUrlRequest = new GeneratePresignedUrlRequest(aliyunOssConfig.getBucketName(), key);
        generatePresignedUrlRequest.setExpiration(expiration);
        URL url = ossClient.generatePresignedUrl(generatePresignedUrlRequest);
        String[] split = url.toString().split("\\?");
        return split[0].replace("-internal", "");
    }

    /**
     * 指定文件名上传图片
     *
     * @param filename 文件名
     * @param data     数据
     * @return
     */
    public AliyunOssResult uploadImg(String filename, byte[] data) {

        InputStream inputStream = new ByteArrayInputStream(data);
        //上传文件
        AliyunOssResult resoult = putFile(inputStream, "png", filename);
        if (resoult.getCode() != 200) {
            log.error("upload0 failed");
            // 如果失敗，重試一次
            resoult = putFile(inputStream, "png", filename);
        }
        return resoult;
    }

    /**
     * 小程序上传jpg格式图片
     *
     * @param filename 包括文件名前缀, 如upload_data/, 文件名前缀会生成相应目录
     * @param data     字节数组
     * @return
     */
    public AliyunOssResult uploadImgByFileName(String filename, byte[] data) {
        log.info("小程序开始上传文件");
        InputStream inputStream = new ByteArrayInputStream(data);
        //上传文件
        AliyunOssResult resoult = putFile(inputStream, "jpg", filename);
        if (resoult.getCode() != 200) {
            log.error("upload0 failed");
            // 如果失敗，重試一次
            resoult = putFile(inputStream, "jpg", filename);
        }
        return resoult;
    }

    /**
     * @param fileType
     * @return String
     * @MethodName: contentType
     * @Description: 获取文件类型
     */
    public String contentType(String fileType) {
        fileType = fileType.toLowerCase();
        String contentType = "";
        switch (fileType) {
            case "bmp":
                contentType = "image/bmp";
                break;
            case "gif":
                contentType = "image/gif";
                break;
            case "png":
            case "jpeg":
            case "jpg":
                contentType = "image/jpeg";
                break;
            case "html":
                contentType = "text/html";
                break;
            case "txt":
                contentType = "text/plain";
                break;
            case "vsd":
                contentType = "application/vnd.visio";
                break;
            case "ppt":
            case "pptx":
                contentType = "application/vnd.ms-powerpoint";
                break;
            case "doc":
            case "docx":
                contentType = "application/msword";
                break;
            case "xml":
                contentType = "text/xml";
                break;
            case "mp4":
                contentType = "video/mp4";
                break;
            default:
                contentType = "application/octet-stream";
                break;
        }
        return contentType;
    }

}